package com.studyweb.controller;

import com.studyweb.pojo.vo.Result;
import com.studyweb.pojo.entity.User;
import com.studyweb.service.UserService;
import com.studyweb.service.EmailService;
import com.studyweb.service.VerificationCodeService;
import com.studyweb.utils.JwtUtils;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 用户控制器
 * 
 * @author StudyWeb Team
 * @since 1.0.0
 */
@Slf4j
@RestController
@RequestMapping("/api/user")
@Validated
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private EmailService emailService;

    @Autowired
    private VerificationCodeService verificationCodeService;

    /**
     * 用户注册接口
     * 
     * @param user 用户信息
     * @return 注册结果
     */
    @PostMapping("/register")
    public Result register(@Valid @RequestBody User user) {
        try {
            // 检查用户名是否已存在
            if (userService.isUsernameExists(user.getUsername())) {
                return Result.error("用户名已存在");
            }
            
            // 检查手机号是否已存在
            if (userService.isPhoneExists(user.getPhone())) {
                return Result.error("手机号已被注册");
            }
            
            // 检查邮箱是否已存在
            if (userService.isEmailExists(user.getEmail())) {
                return Result.error("邮箱已被注册");
            }
            
            // 注册用户
            boolean success = userService.register(user);
            if (success) {
                return Result.success("注册成功");
            } else {
                return Result.error("注册失败");
            }
        } catch (Exception e) {
            log.error("用户注册异常", e);
            return Result.error("注册失败：" + e.getMessage());
        }
    }

    /**
     * 用户登录接口
     * 
     * @param loginData 登录数据
     * @param request HTTP请求
     * @return 登录结果
     */
    @PostMapping("/login")
    public Result login(@RequestBody Map<String, String> loginData, HttpServletRequest request) {
        try {
            String username = loginData.get("username");
            String password = loginData.get("password");
            
            if (!StringUtils.hasText(username) || !StringUtils.hasText(password)) {
                return Result.error("用户名和密码不能为空");
            }
            
            User user = userService.login(username, password, request);
            if (user != null) {
                // 生成JWT token（包含用户类型）
                String token = jwtUtils.generateToken(user.getUserId(), user.getUsername(), user.getUserType());
                
                Map<String, Object> result = new HashMap<>();
                result.put("token", token);
                result.put("user", user);
                
                return Result.success("登录成功", result);
            } else {
                return Result.error("用户名或密码错误");
            }
        } catch (Exception e) {
            log.error("用户登录异常", e);
            return Result.error("登录失败：" + e.getMessage());
        }
    }

    /**
     * 获取当前用户信息
     * 
     * @param request HTTP请求
     * @return 用户信息
     */
    @GetMapping("/info")
    public Result getUserInfo(HttpServletRequest request) {
        try {
            String token = jwtUtils.getTokenFromRequest(request);
            if (token != null) {
                Map<String, Object> claims = jwtUtils.parseToken(token);
                Long userId = Long.valueOf(claims.get("userId").toString());
                
                User user = userService.getUserById(userId);
                if (user != null) {
                    return Result.success(user);
                } else {
                    return Result.error("用户不存在");
                }
            } else {
                return Result.error("未登录");
            }
        } catch (Exception e) {
            log.error("获取用户信息异常", e);
            return Result.error("获取用户信息失败：" + e.getMessage());
        }
    }

    /**
     * 根据用户ID获取用户信息
     * 
     * @param userId 用户ID
     * @return 用户信息
     */
    @GetMapping("/{userId}")
    public Result getUserById(@PathVariable @NotNull Long userId) {
        try {
            User user = userService.getUserById(userId);
            if (user != null) {
                return Result.success(user);
            } else {
                return Result.error("用户不存在");
            }
        } catch (Exception e) {
            log.error("获取用户信息异常", e);
            return Result.error("获取用户信息失败：" + e.getMessage());
        }
    }

    /**
     * 更新用户信息
     * 
     * @param user 用户信息
     * @param request HTTP请求
     * @return 更新结果
     */
    @PutMapping("/update")
    public Result updateUser(@RequestBody User user, HttpServletRequest request) {
        try {
            String token = jwtUtils.getTokenFromRequest(request);
            if (token != null) {
                Map<String, Object> claims = jwtUtils.parseToken(token);
                Long currentUserId = Long.valueOf(claims.get("userId").toString());
                Integer userType = Integer.valueOf(claims.get("userType").toString());
                
                // 只有管理员或用户本人可以更新用户信息
                if (userType == 1 || currentUserId.equals(user.getUserId())) {
                    // 更新用户时不更新密码字段，将密码设为null
                    user.setPassword(null);
                    
                    boolean success = userService.updateUser(user);
                    if (success) {
                        return Result.success("更新成功");
                    } else {
                        return Result.error("更新失败");
                    }
                } else {
                    return Result.error("权限不足");
                }
            } else {
                return Result.error("未登录");
            }
        } catch (Exception e) {
            log.error("更新用户信息异常", e);
            return Result.error("更新失败：" + e.getMessage());
        }
    }

    /**
     * 删除用户
     * 
     * @param userId 用户ID
     * @param request HTTP请求
     * @return 删除结果
     */
    @DeleteMapping("/{userId}")
    public Result deleteUser(@PathVariable @NotNull Long userId, HttpServletRequest request) {
        try {
            String token = jwtUtils.getTokenFromRequest(request);
            if (token != null) {
                Map<String, Object> claims = jwtUtils.parseToken(token);
                Integer userType = Integer.valueOf(claims.get("userType").toString());
                
                // 只有管理员可以删除用户
                if (userType == 1) {
                    boolean deleted = userService.deleteUser(userId);
                    if (deleted) {
                        return Result.success("删除成功");
                    } else {
                        return Result.error("删除失败");
                    }
                } else {
                    return Result.error("权限不足");
                }
            } else {
                return Result.error("未登录");
            }
        } catch (Exception e) {
            log.error("删除用户异常", e);
            return Result.error("删除失败：" + e.getMessage());
        }
    }

    /**
     * 分页查询用户列表
     * 
     * @param pageNum 页码
     * @param pageSize 页大小
     * @param username 用户名
     * @param nickname 昵称
     * @param phone 手机号
     * @param email 邮箱
     * @param status 状态
     * @param userType 用户类型
     * @param request HTTP请求
     * @return 用户列表
     */
    @GetMapping("/list")
    public Result getUserList(
            @RequestParam(defaultValue = "1") int pageNum,
            @RequestParam(defaultValue = "10") int pageSize,
            @RequestParam(required = false) String username,
            @RequestParam(required = false) String nickname,
            @RequestParam(required = false) String phone,
            @RequestParam(required = false) String email,
            @RequestParam(required = false) Integer status,
            @RequestParam(required = false) Integer userType,
            HttpServletRequest request) {
        try {
            String token = jwtUtils.getTokenFromRequest(request);
            if (token != null) {
                Map<String, Object> claims = jwtUtils.parseToken(token);
                Integer currentUserType = Integer.valueOf(claims.get("userType").toString());
                
                // 只有管理员可以查看用户列表
                if (currentUserType == 1) {
                    User queryUser = new User();
                    queryUser.setUsername(username);
                    queryUser.setNickname(nickname);
                    queryUser.setPhone(phone);
                    queryUser.setEmail(email);
                    queryUser.setStatus(status);
                    queryUser.setUserType(userType);
                    PageInfo<User> pageInfo = userService.getUserList(pageNum, pageSize, queryUser);
                    return Result.success(pageInfo);
                } else {
                    return Result.error("权限不足");
                }
            } else {
                return Result.error("未登录");
            }
        } catch (Exception e) {
            log.error("获取用户列表异常", e);
            return Result.error("获取用户列表失败：" + e.getMessage());
        }
    }

    /**
     * 获取所有用户
     * 
     * @param request HTTP请求
     * @return 所有用户
     */
    @GetMapping("/all")
    public Result getAllUsers(HttpServletRequest request) {
        try {
            String token = jwtUtils.getTokenFromRequest(request);
            if (token != null) {
                Map<String, Object> claims = jwtUtils.parseToken(token);
                Integer userType = Integer.valueOf(claims.get("userType").toString());
                
                // 只有管理员可以查看所有用户
                if (userType == 1) {
                    List<User> users = userService.getAllUsers();
                    return Result.success(users);
                } else {
                    return Result.error("权限不足");
                }
            } else {
                return Result.error("未登录");
            }
        } catch (Exception e) {
            log.error("获取所有用户异常", e);
            return Result.error("获取所有用户失败：" + e.getMessage());
        }
    }

    /**
     * 获取用户总数
     * 
     * @param request HTTP请求
     * @return 用户总数
     */
    @GetMapping("/count")
    public Result getUserCount(HttpServletRequest request) {
        try {
            String token = jwtUtils.getTokenFromRequest(request);
            if (token != null) {
                Map<String, Object> claims = jwtUtils.parseToken(token);
                Integer userType = Integer.valueOf(claims.get("userType").toString());
                
                // 只有管理员可以查看用户总数
                if (userType == 1) {
                    long count = userService.getUserCount();
                    return Result.success(count);
                } else {
                    return Result.error("权限不足");
                }
            } else {
                return Result.error("未登录");
            }
        } catch (Exception e) {
            log.error("获取用户总数异常", e);
            return Result.error("获取用户总数失败：" + e.getMessage());
        }
    }

    /**
     * 修改密码
     * 
     * @param passwordData 密码数据
     * @param request HTTP请求
     * @return 修改结果
     */
    @PutMapping("/password")
    public Result changePassword(@RequestBody Map<String, String> passwordData, HttpServletRequest request) {
        try {
            String token = jwtUtils.getTokenFromRequest(request);
            if (token != null) {
                Map<String, Object> claims = jwtUtils.parseToken(token);
                Long userId = Long.valueOf(claims.get("userId").toString());
                
                String oldPassword = passwordData.get("oldPassword");
                String newPassword = passwordData.get("newPassword");
                
                if (!StringUtils.hasText(oldPassword) || !StringUtils.hasText(newPassword)) {
                    return Result.error("旧密码和新密码不能为空");
                }
                
                boolean changed = userService.changePassword(userId, oldPassword, newPassword);
                if (changed) {
                    return Result.success("密码修改成功");
                } else {
                    return Result.error("密码修改失败，请检查旧密码是否正确");
                }
            } else {
                return Result.error("未登录");
            }
        } catch (Exception e) {
            log.error("修改密码异常", e);
            return Result.error("修改密码失败：" + e.getMessage());
        }
    }

    /**
     * 重置用户密码（管理员功能）
     * 
     * @param userId 用户ID
     * @param passwordData 密码数据
     * @param request HTTP请求
     * @return 重置结果
     */
    @PutMapping("/reset-password/{userId}")
    public Result resetPassword(@PathVariable @NotNull Long userId, 
                               @RequestBody Map<String, String> passwordData, 
                               HttpServletRequest request) {
        try {
            String token = jwtUtils.getTokenFromRequest(request);
            if (token != null) {
                Map<String, Object> claims = jwtUtils.parseToken(token);
                Integer userType = Integer.valueOf(claims.get("userType").toString());
                
                // 只有管理员可以重置密码
                if (userType == 1) {
                    String newPassword = passwordData.get("newPassword");
                    
                    if (!StringUtils.hasText(newPassword)) {
                        return Result.error("新密码不能为空");
                    }
                    
                    boolean reset = userService.resetPassword(userId, newPassword);
                    if (reset) {
                        return Result.success("密码重置成功");
                    } else {
                        return Result.error("密码重置失败");
                    }
                } else {
                    return Result.error("权限不足");
                }
            } else {
                return Result.error("未登录");
            }
        } catch (Exception e) {
            log.error("重置密码异常", e);
            return Result.error("重置密码失败：" + e.getMessage());
        }
    }

    /**
     * 更新用户状态
     * 
     * @param userId 用户ID
     * @param statusData 状态数据
     * @param request HTTP请求
     * @return 更新结果
     */
    @PutMapping("/status/{userId}")
    public Result updateUserStatus(@PathVariable @NotNull Long userId, 
                                  @RequestBody Map<String, Integer> statusData, 
                                  HttpServletRequest request) {
        try {
            String token = jwtUtils.getTokenFromRequest(request);
            if (token != null) {
                Map<String, Object> claims = jwtUtils.parseToken(token);
                Integer userType = Integer.valueOf(claims.get("userType").toString());
                
                // 只有管理员可以更新用户状态
                if (userType == 1) {
                    Integer status = statusData.get("status");
                    
                    if (status == null) {
                        return Result.error("状态值不能为空");
                    }
                    
                    boolean updated = userService.updateUserStatus(userId, status);
                    if (updated) {
                        return Result.success("状态更新成功");
                    } else {
                        return Result.error("状态更新失败");
                    }
                } else {
                    return Result.error("权限不足");
                }
            } else {
                return Result.error("未登录");
            }
        } catch (Exception e) {
            log.error("更新用户状态异常", e);
            return Result.error("更新用户状态失败：" + e.getMessage());
        }
    }

    /**
     * 检查用户名是否存在
     * 
     * @param username 用户名
     * @return 检查结果
     */
    @GetMapping("/check-username")
    public Result checkUsername(@RequestParam @NotBlank String username) {
        try {
            boolean exists = userService.isUsernameExists(username);
            Map<String, Object> result = new HashMap<>();
            result.put("exists", exists);
            result.put("available", !exists);
            
            if (exists) {
                return Result.success("用户名已存在", result);
            } else {
                return Result.success("用户名可用", result);
            }
        } catch (Exception e) {
            log.error("检查用户名异常", e);
            return Result.error("检查用户名失败：" + e.getMessage());
        }
    }

    /**
     * 检查手机号是否存在
     * 
     * @param phone 手机号
     * @return 检查结果
     */
    @GetMapping("/check-phone")
    public Result checkPhone(@RequestParam @NotBlank String phone) {
        try {
            boolean exists = userService.isPhoneExists(phone);
            Map<String, Object> result = new HashMap<>();
            result.put("exists", exists);
            result.put("available", !exists);
            
            if (exists) {
                return Result.success("手机号已被注册", result);
            } else {
                return Result.success("手机号可用", result);
            }
        } catch (Exception e) {
            log.error("检查手机号异常", e);
            return Result.error("检查手机号失败：" + e.getMessage());
        }
    }

    /**
     * 检查邮箱是否存在
     * 
     * @param email 邮箱
     * @return 检查结果
     */
    @GetMapping("/check-email")
    public Result checkEmail(@RequestParam @NotBlank String email) {
        try {
            boolean exists = userService.isEmailExists(email);
            Map<String, Object> result = new HashMap<>();
            result.put("exists", exists);
            result.put("available", !exists);
            
            if (exists) {
                return Result.success("邮箱已被注册", result);
            } else {
                return Result.success("邮箱可用", result);
            }
        } catch (Exception e) {
            log.error("检查邮箱异常", e);
            return Result.error("检查邮箱失败：" + e.getMessage());
        }
    }

    /**
     * 用户登出
     * 
     * @return 登出结果
     */
    @PostMapping("/logout")
    public Result logout() {
        try {
            // JWT是无状态的，登出只需要前端删除token即可
            return Result.success("登出成功");
        } catch (Exception e) {
            log.error("用户登出异常", e);
            return Result.error("登出失败：" + e.getMessage());
        }
    }

    /**
     * 发送忘记密码验证码
     * 
     * @param emailData 邮箱数据
     * @return 发送结果
     */
    @PostMapping("/forgot-password/send-code")
    public Result sendForgotPasswordCode(@RequestBody Map<String, String> emailData) {
        try {
            String email = emailData.get("email");
            
            if (!StringUtils.hasText(email)) {
                return Result.error("邮箱不能为空");
            }
            
            // 检查邮箱是否存在
            if (!userService.isEmailExists(email)) {
                return Result.error("该邮箱未注册");
            }
            
            // 生成验证码
            String code = verificationCodeService.generateCode();
            
            // 存储验证码到Redis（5分钟有效期）
            boolean stored = verificationCodeService.storeCode(email, code, 5);
            if (!stored) {
                return Result.error("验证码存储失败");
            }
            
            // 发送邮件
            boolean sent = emailService.sendVerificationCode(email, code);
            
            if (sent) {
                return Result.success("验证码已发送到您的邮箱");
            } else {
                // 如果邮件发送失败，清除已存储的验证码
                verificationCodeService.clearCode(email);
                return Result.error("验证码发送失败");
            }
        } catch (Exception e) {
            log.error("发送忘记密码验证码异常", e);
            return Result.error("发送验证码失败：" + e.getMessage());
        }
    }

    /**
     * 通过验证码重置密码
     * 
     * @param resetData 重置数据
     * @return 重置结果
     */
    @PostMapping("/forgot-password/reset")
    public Result resetPasswordByCode(@RequestBody Map<String, String> resetData) {
        try {
            String email = resetData.get("email");
            String code = resetData.get("code");
            String newPassword = resetData.get("newPassword");
            
            if (!StringUtils.hasText(email) || !StringUtils.hasText(code) || !StringUtils.hasText(newPassword)) {
                return Result.error("邮箱、验证码和新密码不能为空");
            }
            
            // 验证验证码
            boolean valid = verificationCodeService.verifyCode(email, code);
            
            if (!valid) {
                return Result.error("验证码无效或已过期");
            }
            
            // 重置密码
            boolean reset = userService.resetPasswordByVerificationCode(email, code, newPassword);
            
            if (reset) {
                // 验证码已在resetPasswordByVerificationCode中处理
                return Result.success("密码重置成功");
            } else {
                return Result.error("密码重置失败");
            }
        } catch (Exception e) {
            log.error("通过验证码重置密码异常", e);
            return Result.error("密码重置失败：" + e.getMessage());
        }
    }
}